﻿using System;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 数组扩展操作
/// </summary>
public static class ArrayUtil
{
    /// <summary>
    /// 在数组末尾添加一个元素
    /// </summary>
    public static void Add<T>(ref T[] array, T item)
    {
        int length = array != null ? array.Length : 0;
        Array.Resize(ref array, length + 1);
        array[length] = item;
    }

    /// <summary>
    /// 在数组末尾添加一些元素
    /// </summary>
    public static void AddRanage<T>(ref T[] array, T[] items)
    {
        if (items == null || items.Length == 0)
            return;

        int length = array != null ? array.Length : 0;
        Array.Resize(ref array, length + items.Length);
        Array.Copy(items, 0, array, length, items.Length);
    }

    /// <summary>
    /// 判断两个数组内容是否相同
    /// </summary>
    public static bool ArrayEquals<T>(T[] lhs, T[] rhs)
    {
        if (lhs == null)
            return lhs == rhs;
        if (rhs == null)
            return false;
        if (lhs.Length != rhs.Length)
            return false;
        for (int i = 0; i < lhs.Length; ++i)
        {
            if (!Equals(lhs[i], rhs[i]))
                return false;
        }
        return true;
    }

    /// <summary>
    /// 清空数组内容
    /// </summary>
    public static void Clear<T>(ref T[] array)
    {
        if (array == null)
            return;

        Array.Clear(array, 0, array.Length);
        Array.Resize(ref array, 0);
    }

    /// <summary>
    /// 返回数组内是否包含指定元素
    /// </summary>
    public static bool Contains<T>(T[] array, T item)
    {
        return IndexOf(array, item) != -1;
    }

    /// <summary>
    /// 返回数组内符合条件的第一个元素
    /// </summary>
    public static T Find<T>(T[] array, Predicate<T> match)
    {
        if (array == null)
            return default(T);

        foreach (var item in array)
        {
            if (match(item))
                return item;
        }

        return default(T);
    }

    /// <summary>
    /// 返回数组内符合条件的所有元素
    /// </summary>
    public static List<T> FindAll<T>(T[] array, Predicate<T> match)
    {
        var result = new List<T>();
        if (array == null)
            return result;
        
        foreach (var item in array)
        {
            if (match(item))
                result.Add(item);
        }

        return result;

    }

    /// <summary>
    /// 返回数组内符合条件的第一个元素的位置
    /// </summary>
    public static int FindIndex<T>(T[] array, Predicate<T> match)
    {
        if (array == null)
            return -1;

        for (int i = 0; i < array.Length; ++i)
        {
            if (match(array[i]))
                return i;
        }

        return -1;
    }

    /// <summary>
    /// 返回第一个和指定元素相同的元素的位置
    /// </summary>
    public static int IndexOf<T>(T[] array, T item)
    {
        if (array == null)
            return -1;

        for (int i = 0; i < array.Length; ++i)
        {
            if (Equals(array[i], item))
                return i;
        }

        return -1;
    }

    /// <summary>
    /// 返回最后一个和指定元素相同的元素的位置
    /// </summary>
    public static int LastIndexOf<T>(T[] array, T item)
    {
        if (array == null)
            return -1;

        for (int i = array.Length - 1; i >= 0; --i)
        {
            if (Equals(array[i], item))
                return i;
        }

        return -1;
    }

    /// <summary>
    /// 在数组内指定位置插入元素
    /// </summary>
    public static void Insert<T>(ref T[] array, int index, T item)
    {
        int length = array != null ? array.Length : 0;
        index = Mathf.Clamp(index, 0, length);
        Array.Resize(ref array, length + 1);
        Array.Copy(array, index, array, index + 1, length - index);
        array[index] = item;
    }

    /// <summary>
    /// 移除第一个和指定元素相同的元素
    /// </summary>
    public static bool Remove<T>(ref T[] array, T item)
    {
        int index = IndexOf(array, item);
        return RemoveAt(ref array, index);
    }

    /// <summary>
    /// 移除指定位置的元素
    /// </summary>
    public static bool RemoveAt<T>(ref T[] array, int index)
    {
        if (array == null || index < 0 || index >= array.Length)
            return false;

        T[] array2 = new T[array.Length - 1];
        Array.Copy(array, 0, array2, 0, index);
        Array.Copy(array, index + 1, array2, index, array.Length - index - 1);
        array = array2;
        return true;
    }
}
